﻿using FreeSql;
using FreeSql.DatabaseModel;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using Common;
using Common.ResultFormat;

namespace FreeSqlExtend
{
    public class FreeSqlRepositoryBase<T>:IDisposable where T : class
    {
        private readonly ILogger<FreeSqlRepositoryBase<T>> _logger;
        private IFreeSql freeSql = null;
        //private IdleBus<IFreeSql> ib = new IdleBus<IFreeSql>(TimeSpan.FromMinutes(1));
        private readonly string Key = Guid.NewGuid().ToString();
        public virtual string DBName { get; set; }
        public IFreeSql FreeSql
        {
            get
            {
                return freeSql;
            }
        }
        private IBaseRepository<T> repository = null;
        private IBaseRepository<T> Repository 
        { 
            get 
            {
                return repository;
            }
        }
        public FreeSqlRepositoryBase(ILogger<FreeSqlRepositoryBase<T>> logger) 
        {
            freeSql = FreeSqlInitialization.Initialization(DBName);
            if (freeSql.Aop.CurdAfterHandler == null || freeSql.Aop.CurdAfterHandler.GetInvocationList().Length == 0)
            {
                freeSql.Aop.CurdAfter += Aop_CurdAfter;
            }
            if (typeof(T).CustomAttributes.Where(t => t.AttributeType == typeof(SubTableAttribute)).Any())
            {
                repository = this.freeSql.GetGuidRepository<T>(null, oldname => $"{oldname}_{DateTime.Now.ToString("yyyyMM")}");
            }
            else
            {
                repository = this.freeSql.GetGuidRepository<T>();
            }
            _logger = logger;
        }
        private void Aop_CurdAfter(object sender, FreeSql.Aop.CurdAfterEventArgs e)
        {
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.AppendLine(e.Identifier.ToString());
            stringBuilder.AppendLine("耗时" + e.ElapsedMilliseconds + "耗秒" + e.ElapsedTicks);
            string sql = e.Sql.Replace((char)13, (char)0).Replace((char)10, (char)0);
            //foreach (var item in e.DbParms)
            //{
            //    sql = sql.Replace(item.ParameterName, "'" + item.Value.ToString() + "'");
            //}
            stringBuilder.AppendLine(sql);

            if (e.ExecuteResult is List<T>)
            {
                List<T> list = e.ExecuteResult as List<T>;
                stringBuilder.AppendLine("结果："+ list.Count);
            }
            else if (e.ExecuteResult is Object[])
            {
                Object[] list = e.ExecuteResult as Object[];
                stringBuilder.AppendLine("结果：" + list.Length);
            }
            else
            {
                stringBuilder.AppendLine("结果：" + JsonConvert.SerializeObject(e.ExecuteResult));
            }
            
            
            _logger.LogInformation(1,stringBuilder.ToString());
            //_logger.Log(LogLevel.Information, "aabb");
            stringBuilder.Clear();
        }

        public int Delete(T entity) 
        {
            return Repository.Delete(entity);
        }
        public int Delete(Expression<Func<T, bool>> predicate) 
        {
            return Repository.Delete(predicate);
        }
        public T Insert(T entity) 
        {
            return Repository.Insert(entity);
        }
        public Task<T> InsertAsync(T entity, CancellationToken cancellationToken = default) 
        {
            return Repository.InsertAsync(entity, cancellationToken);
        }
        public int Update(T entity) 
        {
            return Repository.Update(entity);
        }
        public List<T> GetAll() 
        {
            return Repository.Where(exp=>true).ToList();
        }
        public List<T> GetByWhere(Expression<Func<T, bool>> exp) 
        {
            return Repository.Where(exp).ToList();
        }
        public T FirstOrDefault(Expression<Func<T, bool>> exp) 
        {
            List<T> list = Repository.Where(exp).ToList();
            return list.FirstOrDefault();
        }
        public PageDataInfo<T> GetPage<TKey>(int pageIndex, int pageSize, Expression<Func<T, bool>> exp, Func<T, TKey> keySelector)
        {
            long count = 0;
            var q = freeSql.Select<T>();
            List<DbTableInfo> dbTableInfos = GetTableNames("");
            foreach (var item in dbTableInfos)
            {
                q = q.AsTable((type, oldname) => item.Name);
            }
            List<T> ts = q.Where(exp).Count(out count).ToList();
            ts = ts.OrderBy(keySelector).Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList();
            _logger.LogInformation(count + "条数据");
            return new PageDataInfo<T>(ts, pageIndex, pageSize, (int)count);
        }
        public List<DbTableInfo> GetTableNames(String name)
        {
            List< DbTableInfo> t2 = freeSql.DbFirst.GetTablesByDatabase(freeSql.DbFirst.GetDatabases()[0]);
            if (string.IsNullOrEmpty(name))
            {
                return t2.FindAll(o => o.Name.StartsWith(typeof(T).Name));
            }
            else
            {
                return t2.FindAll(o => o.Name.StartsWith(name));
            }
            
        }
        public void Dispose()
        {
            //_logger.LogInformation("释放");
            //ib.Get(Key).Dispose();
            //if (IsDis)
            //{

            //Repository.Dispose();
            //ib.Get(Key).Dispose();
          
            //}
        }
    }
}
